#include "tcpserver.h"
#include <sys/types.h>         
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

using namespace VLRTSP;


/**
 * @Author: CimZzz
 * @Date: 2022-01-11 14:26:24
 * 
 * 开始监听端口
 * @return 如果监听成功返回 Socket，否则返回 -1
 * 
 * @note 需要跨平台支持的函数
 */
VL_SOCKET TCPServer::_listen() {
	int socketFd = ::socket(AF_INET, SOCK_STREAM, 0);
	if(socketFd < 0) {
		return -1;
	}
	
	int on = 1;
	setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof on);
	
	struct sockaddr_in addr = {0};			  
	addr.sin_family = AF_INET;		  
	addr.sin_addr.s_addr = inet_addr("0.0.0.0"); 
	addr.sin_port = htons(this->port);  

	if(::bind(socketFd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
		// todo error handle
		return -1;
	}

	if(::listen(socketFd, 1024) == -1) {
		// todo error handle
		return -1;
	}

	return socketFd;
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-11 14:26:38
 * 
 * 销毁 TCPServer 监听
 * 
 * @note 需要跨平台支持的函数
 */
void TCPServer::_destroy() {
	::close(serverFd);
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-11 14:15:45
 * 
 * 接收 Socket
 * @return Socket 指针
 * 
 * @note 需要跨平台支持的函数
 */
TCPSocket* TCPServer::_acceptSocket() {
	struct sockaddr_in addr = {0};
	socklen_t length = (socklen_t) sizeof(addr);
	int socketFd = ::accept(serverFd, (struct sockaddr*)&addr, &length);
	if(socketFd > 0) {
		// 接收成功
		return new TCPSocket(socketFd, std::string(inet_ntoa(addr.sin_addr)), htonl(addr.sin_port));
	}

	return nullptr;
}